package com.java8.stream;

import com.java8.lambda.Employee;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Stream;

/**
 * 创建StreamApi
 * 中间操作
 * 多个中间操作可以连接起来形成一个流水线，
 * 除非流水线上触发终止操作，否则中间操作不会执行任何的处理!
 * 而在终止操作时一次性全部处理，称为惰性求值。
 * <p>
 * 筛选和切片
 * 方法                                                   描述
 * filter                                               接收Lambda,从流中排除某些元素
 * distinct()                                           筛选，通过流所生成元素的hashCode()和equals()去除重复元素
 * limit                                                截断流，使其元素不超过给定数量。
 * skip                                                 跳过元素，返回一个扔掉了前n个元素的流。若流中元素不足N个，则返回一个空流，与limit(n)互补
 * 终止操作
 */
public class TestStream2 {

    //中间操作
    /**
     * 筛选和切片
     * filter                                               接收Lambda,从流中排除某些元素
     * * distinct()                                           筛选，通过流所生成元素的hashCode()和equals()去除重复元素
     * * limit                                                截断流，使其元素不超过给定数量。
     * * skip                                                 跳过元素，返回一个扔掉了前n个元素的流。若流中元素
     */

    List<Employee> employeesList = Arrays.asList(new Employee("张三", 18, 9999.99),
            new Employee("李四", 38, 5555.55),
            new Employee("王五", 50, 6666.66));

    //内部迭代:迭代操作由Stream API完成的
    @Test
    public void test1() {
        //中间操作不会执行任何操作
        Stream<Employee> employeeStream = employeesList.stream().filter(employee -> {
            System.out.println("SteamApi的中间操作");
            return employee.getAge() > 35;
        });

        //终止操作:一次性执行全部内容，即"惰性求值"
        employeeStream.forEach(System.out::println);

    }

    //外部迭代
    @Test
    public void test2() {
        Iterator<Employee> iterator = employeesList.iterator();

        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }

    @Test
    public void test3() {
        //limit,分段取值，只取指定大小范围内的值 distinct去掉重复元素
        employeesList.stream().filter((e) -> e.getSalary() > 5000).limit(2).distinct().forEach(System.out::println);
    }

    @Test
    public void test4() {
        //skip,分段取值，只取指定大小范围外的值
        employeesList.stream().filter(e -> e.getSalary() > 5000).skip(2).forEach(System.out::println);
    }

    //中间操作
    /*
    映射
    map ---接受lambda表达式，将元素转换成其他形式或提取信息，接收一个函数作为参数，该函数会被应用到每个元素上，并将其映射成一个新元素
    flatMap--接收一个函数作为参数，将流中的每个值都换成另一个流，然后把所有流连接成一个流
     */
    @Test
    public void test5() {
        List<String> stringList = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");

        stringList.stream().map(String::toUpperCase).forEach(System.out::println);

        System.out.println("---------------------");
        stringList.stream().map(String::toString).forEach(System.out::println);

        employeesList.stream().map(Employee::getName).forEach(System.out::println);

        Stream<Character> characterStream = stringList.stream().flatMap(TestStream2::filterCharacter);
        characterStream.forEach(System.out::println);
    }


    @Test
    public void test6() {
        List<String> stringList = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");
        Stream<Stream<Character>> streamStream = stringList.stream().map(TestStream2::filterCharacter);
        streamStream.forEach((sm) -> {
            sm.forEach(System.out::println);
        });

    }


    public static Stream<Character> filterCharacter(String str) {
        List<Character> list = new ArrayList<>();

        for (Character character : str.toCharArray()) {
            list.add(character);
        }
        return list.stream();
    }

    //中间操作

    /**
     * 排序
     * sorted()--自然排序
     * sortedn(Comparator com) --定制排序
     */
    @Test
    public void test7() {
        List<String> list = Arrays.asList("ccc", "aaa", "bbb", "eee");
        list.stream().sorted().forEach(System.out::println);

        System.out.println("----------------------");
        employeesList.stream().sorted((e1, e2) -> {
            if(e1.getAge().equals(e2.getAge())){
                return e1.getName().compareTo(e2.getName());
            }else {
                return -e1.getName().compareTo(e2.getName());
            }
        }).forEach(System.out::println);
    }

}
